package controllers;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;

import model.Button;
import model.LoginModel;
import model.MainWindowModel;
import model.UnregisteredUser;
import model.UserGroup;
import model.UserPermissions;
import view.LoginGUI;
import view.MainWindowGUI;
import view.UserRegisterGUI;
import client.CliMessage;
import client.SGI;

/**
 * This Class is a Login window Controller which implements Observer Object.
 * @author Dmitry
 */

public class LoginController extends AbstractController implements IValidateInput 
{
	
	/** The log view. */
	private LoginGUI logView;
	
	/** The log model. */
	private LoginModel logModel;
	
	/**
	 * This is Login controller constructor.
	 * @param logView is a Login window GUI instance.
	 * @param logModel is a Login Model instance which holds the user id and password.
	 */
	public LoginController(LoginGUI logView, LoginModel logModel ) 
	{
		super(logView,logModel);
		this.logView = logView;
		this.logModel = logModel;
		logView.addRegisterActionListener(new RegisterListener(this));
		logView.addLoginActionListener(new LoginListener());
	}
	
	

	
	/**
	 * This method validates that all of the mandatory fields were filled.
	 */
	@Override
	public boolean validateInput() 
	{
		String uid = logView.getUserIDFiled();
		String pwd = logView.getPasswordField();
		if(uid.equals("") || pwd.equals(""))
		{
			logView.displayWrnMessage("Error: You must fill all fields!");
			return false;
		}
		else
		{
			try
			{
				Integer.parseInt(uid);
				logView.undisplayWrnMessage();
				return true;
			}
			catch (Exception e)
			{
				logView.displayWrnMessage("Error: Elegal charchters in ID");
				return false;
			}
		}
	}


	/**
	 * The listener interface for receiving register events.
	 * This class handles "Register" button clicks.
	 * @see RegisterEvent
	 */
	class RegisterListener extends AbstractListener
	{
		
		/** The previous listener. */
		private LoginController previousListener;
		
		/**
		 * Instantiates a new register listener.
		 *
		 * @param prevListener the prev listener
		 */
		public RegisterListener(LoginController prevListener){
			this.previousListener = prevListener;
		}
		
		/**
		 * This method handles "Register" button clicks.
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) 
		{
			UnregisteredUser regModel = new UnregisteredUser();
			UserRegisterGUI regView = new UserRegisterGUI();
			RegisterController regController = new RegisterController(regView,regModel);
			
			//add observer to new controller and delete the rest
			setCurrentObserver(regController);
			
			// Create new Back Listener
			setBackListener(previousListener, regView);
		}
	}
	
	
	/**
	 * The listener interface for receiving login events.
	 * This class handles "Login" button clicks.
	 * @see LoginEvent
	 */
	class LoginListener implements ActionListener
	{
		
		/**
		 * This method handles "Login" button clicks.
		 * It searches if this person is already exists in the DB.
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) 
		{
			if(!validateInput())
				return;
			logModel.setUserID(new String(logView.getUserIDFiled()));
			logModel.setPassword(new String(logView.getPasswordField()));
				
			String searchQuery2 = "search"	+"SELECT g.gid,g.gname,gb.bid,b.bname "
											+"FROM groups AS g ,group_buttons AS gb,buttons AS b "
											+"WHERE g.gid = gb.gid AND gb.bid = b.bid"
											+" AND gb.gid IN (SELECT ug.gid "
											+				 "FROM user AS u , user_groups AS ug "
											+				 "WHERE u.uid = " + logModel.getUserID()
											+				 " AND u.password LIKE '"+ logModel.getPassword()+"'"
											+				 " AND u.loginStatus = 0"
											+				 " AND u.uid = ug.uid) "
											
											+"UNION "
											
											+"SELECT g.gid,g.gname,NULL,NULL "
											+"FROM groups AS g ,group_buttons AS gb "
											+"WHERE g.gid IN (SELECT ug.gid "
											+				"FROM user AS u , user_groups AS ug " 
											+				"WHERE u.uid = " + logModel.getUserID() 
											+				" AND u.password LIKE '"+ logModel.getPassword()+"'"
											+				" AND u.loginStatus = 0" 
											+				" AND u.uid = ug.uid)"
											+" AND NOT EXISTS (SELECT * "
											+					"FROM group_buttons gb2,buttons AS b2 "
											+					"WHERE g.gid = gb2.gid AND gb2.bid = b2.bid)";
			
			sendToServer(searchQuery2);
		}
	}

	/**
	 * This method handles DB request success. If the login operation succeeded 
	 * the main window is opened.
	 */
	@Override
	public void handleDBRequestSuccess()
	{
		//close login window
		logView.setVisible(false);
		
		//open main window with the correct buttons
		System.out.println("Main Window Opens");
		MainWindowGUI mainView = new MainWindowGUI();
		MainWindowModel mainModel = new MainWindowModel();
		MainWindowController mainController = new MainWindowController(mainView, mainModel);
		
		//set main window controller as the observer
		SGI.clnt.deleteObserver(this);
		SGI.clnt.addObserver(mainController);
	}

	/**
	 * This method handles DB results. 
	 * It gets all the buttons according to user's groups and permissions.
	 */
	@Override
	public void handleDBSearchResult(CliMessage dbResult) 
	{	
		//get user permissions from the DB and save them in a new UserPermissions singleton:
		//allocate a new ArrayList<UserGroup> and add the groups that the user is assigned to.
		//assign each group its buttons.
		
		int uid =Integer.parseInt(logModel.getUserID());
		int n = dbResult.getSrs().size();
		
		ArrayList<UserGroup> userGroups = new ArrayList<UserGroup>(); //set a new group array list
		ArrayList<HashMap<String, String>> lst = dbResult.getSrs(); //get the tuples list
		HashMap<String,String> tuple,tempTuple;
		
		//get all group buttons
		ArrayList<Button> userButtons = new ArrayList<Button>();
		
		for(int i = 0; i<n ;i++)
		{
			//get a tuple which consists of: [gid,gname,bid,bname]
			tuple = lst.get(i);	
			
			//create a new group 
			int gid = Integer.parseInt(tuple.get("GID"));
			String gname = tuple.get("GNAME");
			UserGroup group = new UserGroup(gid , gname);
			
			int gid2 = gid;
			tempTuple = tuple;
			
			while(gid2 == gid && i<n) // if the next tuple exists
			{
				
				//if the group has buttons - add them to the group buttons 
				if(!tempTuple.get("BID").equals(""))
				{
					int bid = Integer.parseInt(tempTuple.get("BID"));
					String bname = tempTuple.get("BNAME");
					Button b = new Button(bid,bname);
					userButtons.add(b);
				}
				
				/////print to console for test
				System.out.println(gid +" "+ gname+" "+tempTuple.get("BID")+" "+tempTuple.get("BNAME"));
				/////
				
				if(++i<n)
				{
					//get a tuple
					tempTuple = lst.get(i);
					gid2 =  Integer.parseInt(tempTuple.get("GID"));
				}
			}
			
			i--;
			
			//add group to user
			userGroups.add(group);
		}

		//set the user's permissions
		 UserPermissions.getInstance(uid,userGroups,userButtons);
		
		//change user status in DB to Logged in 
		String updateQuary = "adu"+	"UPDATE user " +
			    					"SET loginStatus = 1 " +
			    					"WHERE uid = " + uid;

		sendToServer(updateQuary);
				
	}
	

	/**
	 * This method handles null DB result.
	 * It prints an error message if the result from the DB was null.
	 */
	@Override
	public void handleNullSearchResult() 
	{
		logView.displayWrnMessage("Error: Check ID and Password!");
		return;	
	}

}
